home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / programming / aros / exec / releasesemaphore.c < prev    next >
C/C++ Source or Header  |  1996-09-13  |  4KB  |  157 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: releasesemaphore.c,v 1.5 1996/09/13 17:51:24 digulla Exp $
  4.     $Log: releasesemaphore.c,v $
  5.     Revision 1.5  1996/09/13 17:51:24  digulla
  6.     Use IPTR
  7.  
  8.     Revision 1.4  1996/08/13 13:56:05  digulla
  9.     Replaced __AROS_LA by __AROS_LHA
  10.     Replaced some __AROS_LH*I by __AROS_LH*
  11.     Sorted and added includes
  12.  
  13.     Revision 1.3  1996/08/01 17:41:16  digulla
  14.     Added standard header for all files
  15.  
  16.     Desc:
  17.     Lang: english
  18. */
  19. #include "exec_intern.h"
  20. #include "semaphores.h"
  21.  
  22. /*****************************************************************************
  23.  
  24.     NAME */
  25.     #include <exec/semaphores.h>
  26.     #include <clib/exec_protos.h>
  27.  
  28.     __AROS_LH1(void, ReleaseSemaphore,
  29.  
  30. /*  SYNOPSIS */
  31.     __AROS_LHA(struct SignalSemaphore *, sigSem, A0),
  32.  
  33. /*  LOCATION */
  34.     struct ExecBase *, SysBase, 95, Exec)
  35.  
  36. /*  FUNCTION
  37.     Releases a lock on a semaphore obtained with either ObtainSemaphore(),
  38.     ObtainSemaphoreShared(), AttemptSemaphore or AttemptSemaphoreShared().
  39.     Each call to one of those functions must be accompanied with one
  40.     call to ReleasSemaphore().
  41.  
  42.     INPUTS
  43.     sigSem - pointer to semaphore structure
  44.  
  45.     RESULT
  46.  
  47.     NOTES
  48.     This function preserves all registers.
  49.  
  50.     EXAMPLE
  51.  
  52.     BUGS
  53.  
  54.     SEE ALSO
  55.  
  56.     INTERNALS
  57.  
  58.     HISTORY
  59.     29-10-95    digulla automatically created from
  60.                 exec_lib.fd and clib/exec_protos.h
  61.     22-01-96    fleischer implementation
  62.  
  63. *****************************************************************************/
  64. {
  65.     __AROS_FUNC_INIT
  66.     __AROS_BASE_EXT_DECL(struct ExecBase *,SysBase)
  67.  
  68.     /* Arbitrate for the semaphore structure */
  69.     Forbid();
  70.  
  71.     /* Lower the use count. >0 means exclusive, <0 shared locked */
  72.     if(sigSem->ss_NestCount>0)
  73.     sigSem->ss_NestCount--;
  74.     else
  75.     sigSem->ss_NestCount++;
  76.  
  77.     /*
  78.     Now if the semaphore is free and there are other tasks waiting
  79.     wake them up.
  80.     */
  81.     if(!sigSem->ss_NestCount&&sigSem->ss_WaitQueue.mlh_Head->mln_Succ!=NULL)
  82.     {
  83.     /* Get first node in the waiting list */
  84.     struct SemaphoreNode *sn;
  85.     sn=(struct SemaphoreNode *)sigSem->ss_WaitQueue.mlh_Head;
  86.  
  87.     /* Is it a shared lock? */
  88.     if((IPTR)sn->node.ln_Name!=SM_EXCLUSIVE)
  89.     {
  90.         /* Yes. Process all shared locks in the list. */
  91.         while(sn->node.ln_Succ!=NULL)
  92.         {
  93.         /* Remember node */
  94.         struct SemaphoreNode *on=sn;
  95.  
  96.         /* Get next node now because there is a Remove() lurking */
  97.         sn=(struct SemaphoreNode *)sn->node.ln_Succ;
  98.  
  99.         /* Is this a shared lock? */
  100.         if((IPTR)on->node.ln_Name!=SM_EXCLUSIVE)
  101.         {
  102.             /* Yes. Remove it from the list */
  103.             Remove(&on->node);
  104.  
  105.             /* Wake the new owner. Check access type. */
  106.             if(on->node.ln_Pri==SN_TYPE_OBTAIN)
  107.             /* ObtainSemaphore() type. Send the semaphore signal. */
  108.             Signal(on->task,SEMAPHORESIGF);
  109.             else
  110.             {
  111.             /* Procure() type. Reply the semaphore message. */
  112.             ((struct SemaphoreMessage *)on)->ssm_Semaphore=sigSem;
  113.             ReplyMsg((struct Message *)on);
  114.             }
  115.  
  116.             /*
  117.             Mark the semaphore as having one more openers.
  118.             This happens here because the new owner(s) may need
  119.             some time to really wake up and I don't want other
  120.             tasks obtaining the semaphore before him.
  121.             */
  122.             sigSem->ss_NestCount--;
  123.         }
  124.         /* Dito. Invalidate the owner field. */
  125.         sigSem->ss_Owner=NULL;
  126.         }
  127.     }else
  128.     {
  129.         /* The new owner wants an exclusive lock. Remove him from the list. */
  130.         Remove(&sn->node);
  131.  
  132.         /* Check access type */
  133.         if(sn->node.ln_Pri==SN_TYPE_OBTAIN)
  134.         {
  135.         /*
  136.             ObtainSemaphore() type. Set the owner field and
  137.             Send the semaphore signal.
  138.         */
  139.         sigSem->ss_Owner=sn->task;
  140.         Signal(sn->task,SEMAPHORESIGF);
  141.         }else
  142.         {
  143.         /* Procure() type. Reply the message. */
  144.         ((struct SemaphoreMessage *)sn)->ssm_Semaphore=sigSem;
  145.         sigSem->ss_Owner=((struct Message *)sn)->mn_ReplyPort->mp_SigTask;
  146.         ReplyMsg((struct Message *)sn);
  147.         }
  148.         /* Mark the semaphore as having one more openers. */
  149.         sigSem->ss_NestCount++;
  150.     }
  151.     }
  152.  
  153.     /* All done. */
  154.     Permit();
  155.     __AROS_FUNC_EXIT
  156. } /* ReleaseSemaphore */
  157.